home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / kcl / akcl / akcl1615.lha / c / cmac.c < prev    next >
C/C++ Source or Header  |  1992-01-05  |  6KB  |  323 lines

  1. #ifndef FIRSTWORD
  2. #include "include.h"
  3. #endif
  4. #include "mp.h"
  5. #include "arith.h"  
  6. #include "num_include.h"
  7.  
  8.  
  9. /* I believe the instructions used here are ok for 68010.. */
  10.  
  11. #ifdef MC68K
  12. #define MC68020
  13. #endif
  14.   
  15. static
  16. object *modulus;
  17. #define FIXNUMP(x) (type_of(x)==t_fixnum)
  18.  
  19. /* Note: the modulus is guaranteed > 0 */
  20.  
  21. #define FIX_MOD(X,MOD) {register int MOD_2; \
  22.                  if (X > (MOD_2=(MOD >>1))) X=X-MOD; else \
  23.                    if (X < -MOD_2)  X=X+MOD;}
  24.  
  25.  
  26.  
  27. #define MYmake_fixnum(doto,x) \
  28.   {register int CMPt1; \
  29.    doto \
  30.    ((((CMPt1=(x))+1024)&-2048)==0?small_fixnum(CMPt1):make_fixnum(CMPt1));}
  31.  
  32. void siLcmod();
  33. void siLcplus();
  34. void siLctimes();
  35. void siLcdifference();
  36.  
  37.  
  38. object ctimes(),cplus(),cdifference(),cmod();
  39.  
  40.  
  41.      
  42. init_cmac()
  43. {
  44. /* add_symbol("ctimes",&ctimes,"cplus",&cplus,"cdifference",&cdifference,"cmod",
  45.  &cmod, 0); */
  46. modulus = (&((make_si_special("MODULUS",Cnil))->s.s_dbind));
  47. make_si_function("CMOD",siLcmod);
  48. make_si_function("CPLUS",siLcplus);
  49. make_si_function("CTIMES",siLctimes);
  50. make_si_function("CDIFFERENCE",siLcdifference);
  51.  
  52. }
  53.  
  54. /* if hi < 0 this is taken to be the two's complement expression of
  55.    a bignum  */
  56. object
  57. signed_bignum2(hi,lo)
  58.      int hi,lo;
  59.   GEN w;
  60.   object result;
  61.   long u[4];
  62.   u[0] = 0x01010004;
  63.   u[1] = 0x01010004;
  64.   u[2] = 0;
  65.   u[3] = 0;
  66.   
  67.   if (hi < 0)
  68.       { setsigne(u,-1);
  69.     if (lo > 0) /* no borrow */
  70.      { lo = -lo;
  71.        hi = -hi;}
  72.        else {hi -= 1;
  73.          hi = -hi;}
  74.      }
  75.   else
  76.     if (hi > 0)
  77.       {setsigne(u,1);
  78.      }
  79.   else /*hi==0 */
  80.     { setsigne(u,1);
  81.       setlgef(u,3);
  82.       MP_LOW(u,3) = lo;
  83.       result = make_integer(u);
  84.       setlgef(u,4);
  85.       return result;}
  86.   /* its length 4 */
  87.   MP_START_LOW(w,u,4);
  88.   MP_NEXT_UP(w) = lo;
  89.   MP_NEXT_UP(w) = hi;
  90.   return(make_integer(u));
  91. }
  92.   
  93.   
  94.   
  95.        
  96.       
  97.  
  98. #ifdef MC68020
  99. /*    
  100. int
  101. dblrem(m,n,mod)
  102. int m,n,mod;
  103. { asm("movl a6@(8),d1");
  104.   asm("mulsl a6@(12),d0:d1");
  105.   asm("divsl a6@(16),d0:d1");
  106. }
  107. */
  108. #endif
  109.  
  110. object make_integer();  
  111.  
  112. static unsigned long small_pos_int[3]={0x1000003,0x01000003,0};
  113. static unsigned long small_neg_int[3]={0x1000003,0xff000003,0};
  114. static unsigned long s4_neg_int[4]={0x1000004,0xff000004,1,0};
  115.  
  116. object
  117. fplus(a,b)
  118.      int a,b;
  119. { int z ;
  120.   int x;
  121.   if (a >= 0)
  122.    { if (b >= 0)
  123.        { x = a + b;
  124.      if (x == 0) return small_fixnum(0);
  125.      small_pos_int[2]=x;
  126.      return make_integer(small_pos_int);
  127.        }
  128.      else
  129.        { /* b neg */
  130.      x = a + b;
  131.      MYmake_fixnum(return,x);
  132.        }}
  133.   else
  134.     { /* a neg */
  135.       if (b >= 0)
  136.     { x = a + b;
  137.       MYmake_fixnum(return,x);
  138.     }
  139.       else
  140.     { /* both neg */
  141.         { unsigned long Xtx,Xty,overflow,Xtres;
  142.           Xtres = addll(-a,-b);
  143.           if (overflow)
  144.         { 
  145.           s4_neg_int[3]=Xtres;
  146.           return make_integer(s4_neg_int);}
  147.           else
  148.         { small_neg_int[2]=Xtres;
  149.           return make_integer(small_neg_int);}
  150.         }}}
  151. }
  152.  
  153.  
  154. object
  155. fminus(a,b)
  156.      int a,b;
  157. { int z ;
  158.   int x;
  159.   if (a >= 0)
  160.    { if (b >= 0)
  161.        { x = a - b;
  162.      MYmake_fixnum(return,x);
  163.      }
  164.      else
  165.        { /* b neg */
  166.      x = a - b;
  167.      if (x==0) return small_fixnum(0);
  168.      small_pos_int[2]=x;
  169.      return make_integer(small_pos_int);
  170.        }}
  171.   else
  172.     { /* a neg */
  173.       if (b <= 0)
  174.     { x = a - b;
  175.       MYmake_fixnum(return,x);
  176.     }
  177.       else
  178.     {  /* b positive */
  179.         { unsigned long Xtx,Xty,overflow,Xtres;
  180.           unsigned long t[4];
  181.           Xtres = addll(-a,b);
  182.           if (overflow)
  183.         { s4_neg_int[3]=Xtres;
  184.           return make_integer(s4_neg_int);}
  185.           else
  186.         { small_neg_int[2]=Xtres;
  187.           return make_integer(small_neg_int);}
  188.         }}}
  189. }
  190.        
  191. #define our_minus(a,b) ((FIXNUMP(a)&&FIXNUMP(b))?fminus(fix(a),fix(b)): \
  192.             number_minus(a,b))
  193. #define our_plus(a,b) ((FIXNUMP(a)&&FIXNUMP(b))?fplus(fix(a),fix(b)): \
  194.             number_plus(a,b))
  195. #define our_times(a,b) number_times(a,b)
  196.  
  197. int
  198. dblrem(a,b,mod)
  199. int a,b,mod;
  200. {int h,l,sign;
  201.  if (a<0) 
  202.    {a= -a; sign= (b<0)? (b= -b,1) :-1;}
  203.  else { sign= (b<0) ? (b= -b,-1) : 1;}
  204.  
  205.  l = mulul(a,b,h);
  206.  b = divul(l,mod,h);
  207.  return ((sign<0) ? -h :h);}
  208.  
  209.  
  210. object      
  211. cmod(x)
  212. object x;
  213. {register object mod = *modulus;
  214.  if (mod==Cnil) return(x);
  215. else
  216.  if((type_of(mod)==t_fixnum && type_of(x)==t_fixnum))
  217.     {register int xx,mm;
  218.      mm=fix(mod);
  219.      if (mm==2) {xx= (fix(x) & 1); return(small_fixnum(xx));}
  220.      xx=(fix(x)%mm);
  221.      FIX_MOD(xx,mm);
  222.      MYmake_fixnum(return,xx);
  223.    }
  224.  else
  225.    {object qp,rp,mod2;
  226.     int compare;
  227.     integer_quotient_remainder_1(x,mod,&qp,&rp);
  228.     mod2=shift_integer(mod,-1);
  229.     compare = number_compare(rp,small_fixnum(0));
  230.     if (compare >= 0)
  231.       {compare=number_compare(rp,mod2);
  232.        if (compare > 0) rp=number_minus(rp,mod);}
  233.     else
  234.       if (number_compare(number_negate(mod2), rp) > 0)
  235.     {rp = number_plus(rp,mod);}
  236.     return rp;}}
  237.  
  238. object
  239. ctimes(a,b)
  240. object a,b;
  241. {object mod = *modulus;
  242.  if (FIXNUMP(mod))
  243.      {register int res, m ;
  244.       res=dblrem(fix(a),fix(b),m=fix(mod));
  245.       FIX_MOD(res,m);
  246.       MYmake_fixnum(return,res);}
  247. else if (mod==Cnil)
  248.   { return(our_times(a,b));}
  249. return cmod(number_times(a,b));}
  250.  
  251.  
  252. object
  253. cdifference(a,b)
  254. object a,b;
  255. {object mod = *modulus;
  256.  if (FIXNUMP(mod))
  257.    {register int res,m;
  258.     res=((fix(a)-fix(b))%(m=fix(mod)));
  259.     FIX_MOD(res,m);
  260.     MYmake_fixnum(return,res);}
  261.  else if (mod==Cnil)
  262.      return (our_minus(a,b));
  263.  else return(cmod(number_minus(a,b)));}
  264.  
  265. object
  266. cplus(a,b)
  267. object a,b;
  268. {object mod = *modulus;
  269.  if (FIXNUMP(mod))
  270.    {register int res,m;
  271.     res=((fix(a)+fix(b))%(m=fix(mod)));
  272.     FIX_MOD(res,m);
  273.     MYmake_fixnum(return,res);}
  274.  else
  275.    if (mod==Cnil)
  276.      return (our_plus(a,b));
  277.  else
  278.    return(cmod(number_plus(a,b)));}
  279.  
  280. void
  281. siLcmod()
  282. {check_arg(1);
  283.  vs_base[0]=cmod(vs_base[0]);
  284. }
  285.  
  286. void
  287. siLcplus()
  288. {register object *base;
  289.  base=vs_base;
  290.  check_arg(2);
  291.  base[0]=cplus(base[0],base[1]);
  292.  vs_top=base+1;
  293. }
  294.  
  295. void
  296. siLctimes()
  297. {register object *base;
  298.  base=vs_base;
  299.  check_arg(2);
  300.  base[0]=ctimes(base[0],base[1]);
  301.  vs_top=base+1;
  302. }
  303.  
  304. void
  305. siLcdifference()
  306. {register object *base;
  307.  base=vs_base;
  308.  check_arg(2);
  309.  base[0]=cdifference(base[0],base[1]);
  310.  vs_top=base+1;
  311. }
  312.  
  313. object 
  314. memq(a,b)
  315. register object a,b;
  316. {while (1)
  317.     {if ((a==b->c.c_car)||b==Cnil) return b;
  318.     b=b->c.c_cdr;}}
  319.  
  320.  
  321.  
  322.